/*************
author:: libo
license:: MIT
*****************/
#include<Mesh_IO/Mesh_IO.h>
#include<Mesh/libcell_iterator.h>
#define _ReadOff_   LibCell_ReadOff_
#define _ReadCell_  LibCell_ReadCell_
#define _WriteCell_ LibCell_WriteCell_
#define _ReadArray_ LibCell_ReadArray_
#define _WriteOff_ LibCell_WriteOff_
#define _ReadObj_ LibCell_ReadObj_


#define iterator_v lib_cell_iterator_vertices
#define iterator_f lib_cell_iterator_faces
#define iterator_c lib_cell_iterator_cells
#define quote lib_cell_quote
//#include<sys/sysinfo.h>
//num[3]
void _ReadArray_(template_m*m,double**V,int**F,int**C,int*num,int back_dim,int manifold_dim)
{
//#ifdef MANIFOLD_REQUIRE
    m->dimension=manifold_dim;
//#endif
	int n=back_dim;
    for(int i=0;i<num[0];i++)
    {
        template_v* v=m->create_vertex(m);
	    v->point_size=n;
        v->point=(double*)malloc(sizeof(double)*n);
        for(int j=0;j<n;j++)
	    {   
            v->point[j]=V[i][j];   
	    }
    }
    int cols;
	if(F==NULL||num[1]==0)
	{
		m->simplex=1;
        for(int i=0;i<num[2];i++)
        {    
            cols=C[i][0];
            template_v** temp_v=(template_v**)malloc(sizeof(template_v*)*cols);
            //template_v* temp_v[cols];
            for(int j=0;j<cols;j++)
	        {
                int id=C[i][j+1];
                template_v* v=NULL;

         
                v=m->get_vertexp(m,id);
                if(v==NULL)
                {
                    free(temp_v);
                    printf("can t find this vertex: %d\r\n",id);
                    return ;
                }
		        temp_v[j]=v;
	        }
	        m->create_cellv(m,temp_v,cols);
            free(temp_v);   
        }
	}
	else
	{
        m->simplex=0;
        for(int i=0;i<num[1];i++)
        {
            cols=F[i][0];
            template_v**temp_v=(template_v**)malloc(sizeof(template_v*)*cols);
            //template_v* temp_v[cols];
                
            for(int j=0;j<cols;j++)
            {
                int id=F[i][j+1];

                template_v* v=NULL;
              
                v=m->get_vertexp(m,id);
                //v=(template_v*)(m->vertices_r->find(m->vertices_r,id));
                if(v==NULL)
                {
                    free(temp_v);
                    printf("can t find this vertex\r\n");
                    return;
                }

                temp_v[j]=v;
                     
            }
            template_f* temp_f=m->create_facev(m,temp_v,cols);
            m->create_halfface(m,temp_f,temp_v,cols);  
            free(temp_v);
        }
        for(int i=0;i<num[2];i++)
        {
                cols=C[i][0];
                template_hf**temp_hf=(template_hf**)malloc(sizeof(template_hf*)*cols); 
                //template_hf* temp_hf[cols];
                for(int j=0;j<cols;j++)
                {
                    int id=C[i][j+1];

                    template_hf * hf=NULL;

                 
                    hf=m->get_halffacep(m,id);
                   // hf=(template_hf*)(m->halffaces_r->find(m->halffaces_r,id));
                    if(hf==NULL)
                    {
                        free(temp_hf);
                        printf("can t find this halfface\n");
                        return ;
                    }
                
                    temp_hf[j]=hf;
                
                
                }
                m->create_cellf(m,temp_hf,cols);
                free(temp_hf);
        }

    
    }
}

void _ReadCell_(template_m*m,char const*filename)
{
    int result=0;
#ifdef _WIN32
    FILE *infile;
    fopen_s(&infile,filename,"r");
#else
    FILE *infile=fopen(filename,"r");
#endif
    if(!infile)
	{
	    printf("cant't open this file\r\n");
	    return;
	}
    fseek(infile,0,SEEK_SET);
    char off[20];
    result=fscanf(infile,"%s",off);
    if(strcmp("CELL",off)==0)
    {
        //printf("cell read\n");
        result=fscanf(infile,"%s",off);
        int n;
        result=fscanf(infile,"%d",&n);
        result=fscanf(infile,"%s",off);
        int manifold_dim;
        result=fscanf(infile,"%d",&manifold_dim);
//#ifdef MANIFOLD_REQUIRE
        m->dimension=manifold_dim;
//#endif
        result=fscanf(infile,"%s",off);
        int simplex;
        int num[3];
        result=fscanf(infile,"%d",&simplex);m->simplex=simplex;
        result=fscanf(infile,"%d %d %d",&num[0],&num[1],&num[2]);
        for(int i=0;i<num[0];i++)
        {
                template_v* v=m->create_vertex(m);
	            v->point_size=n;
                v->point=(double*)malloc(sizeof(double)*n);
                for(int j=0;j<n;j++)
	            {   
                    result=fscanf(infile,"%lf",&(v->point[j]));
	            }
        
        }
        if(simplex==1)
        {
            int cols=0,id=0;
            for(int i=0;i<num[2];i++)
            {
                result=fscanf(infile,"%d",&cols);
                template_v** temp_v=(template_v**)malloc(sizeof(template_v*)*cols); 
                //template_v* temp_v[cols];
                for(int j=0;j<cols;j++)
	            {
                    result=fscanf(infile,"%d",&id);

                    template_v* v=NULL;

		         
                    v=m->get_vertexp(m,id);
                    if(v==NULL)
                    {
                        free(temp_v);
                        printf("can t find this vertex: %d\r\n",id);
                        return;
                    }

		            temp_v[j]=v;
	            }
	            m->create_cellv(m,temp_v,cols);
                free(temp_v);
            
            }
             
        }
        else
        {   
		    m->simplex=0;

//		printf("simplex:%d\n",simplex);
            int cols,id;
            for(int i=0;i<num[1];i++)
            {
                result=fscanf(infile,"%d",&cols);
                //template_v* temp_v[cols];
                template_v**temp_v=(template_v**)malloc(sizeof(template_v*)*cols);
                for(int j=0;j<cols;j++)
                {
                    result=fscanf(infile,"%d",&id);
                    template_v* v=NULL;

                    v=m->get_vertexp(m,id);
                    if(v==NULL)
                    {
                        printf("can t find this vertex:%d\r\n",id);
                        free(temp_v);
                        return;
                    }

                    temp_v[j]=v;                
                }
                template_f* temp_f=m->create_facev(m,temp_v,cols);
                m->create_halfface(m,temp_f,temp_v,cols); 
                free(temp_v);           
            }
            for(int i=0;i<num[2];i++)
            {
                result=fscanf(infile,"%d",&cols);
                //temp_hf放到循环外面
                //template_hf* temp_hf[cols];
                template_hf**temp_hf=(template_hf**)malloc(sizeof(template_hf*)*cols);
                for(int j=0;j<cols;j++)
                {
                    result=fscanf(infile,"%d",&id);

                    template_hf * hf=NULL;

                  
                    hf=m->get_halffacep(m,id); 
                    //hf=(template_hf*)(m->halffaces_r->find(m->halffaces_r,id));
                    if(hf==NULL)
                    {
                        free(temp_hf);
                        printf("can t find this halfface:%d\n",id);
                        return;
                    }

                
                    temp_hf[j]=hf;         
                }
                m->create_cellf(m,temp_hf,cols);
                free(temp_hf);
            }
        }    
    }
    fclose(infile);

}
Node* _ReadM_(template_m*m,char const *filename)
{
    int result=0;
    char* result1=NULL;
    m->simplex=1;
//#ifdef MANIFOLD_REQUIRE
    m->dimension=2;
//#endif
#ifdef _WIN32
    FILE *infile;
    fopen_s(&infile,filename,"r");
#else
    FILE *infile=fopen(filename,"r");
#endif
    if(!infile)
    {
        printf("cant't open this file\r\n");
        return NULL;
    }
    fseek(infile,0,SEEK_SET);
    char MM[20];
    char  temp_m[110];
    Node * n_c=NULL;
    Int_RB_Tree* tree=(Int_RB_Tree*)malloc(sizeof(Int_RB_Tree));
    int_rb_tree_init(tree);
    while(result=fscanf(infile,"%s",MM)>0)
    {
        int temp_id;
        result=fscanf(infile,"%d",&temp_id);
        if(MM[0]=='#')
        {
            result1=fgets(temp_m,110,infile);
        }
        if(strcmp("Vertex",MM)==0)
        {
            template_v* v=m->create_vertex(m);
            // rbt.key=temp_id;
            // rbt.value=v;
            // tree->insert(tree,&rbt);
            tree->insert(tree,temp_id,v);
            v->point_size=3;
            v->point=(double*)malloc(sizeof(double)*3);
            for(int i=0;i<3;i++)
            {
                result=fscanf(infile,"%lf",&(v->point[i]));
                
            }
            result1=fgets(temp_m,110,infile);  
            if(temp_m[2]=='r'&&temp_m[3]=='g'&&temp_m[4]=='b')
            {
                double *temp_d=(double*)malloc(sizeof(double)*3);
                n_c=node_overlying(n_c,temp_d); 
                sscanf(&(temp_m[7]),"%lf %lf %lf ",&(temp_d[0]),&(temp_d[1]),&(temp_d[2]));

              //  printf("shi:%lf %lf %lf\n",temp_d[0],temp_d[1],temp_d[2]); 
            }

            //printf("%s\n",temp_m);
        }
        else if(strcmp("Face",MM)==0)
        {
            template_v * vs[3];
            int id=0;
            for(int i=0;i<3;i++)
            {   
                result=fscanf(infile,"%d",&id);

                // rbt.key=id;
                // rbt1=(RB_int*)(tree->find(tree,&rbt));
                // if(rbt1==NULL)
                // {
                //     printf("cant find vertex\n");
                //     return n_c;
                // }
                // else
                // {
                //    vs[i]=(template_v*)(rbt1->value); 
                // }
                vs[i]=(template_v*)(tree->find(tree,id));
                if(vs[i]==NULL)
                {
                    int_rb_tree_free(tree);
                    printf("cant find vertex\n");
                    return n_c;
                } 
                /*auto it=m->vertices.find(id-1);
                if(it!=m->vertices.end())
                {
                    vs[i]=it->second;
                } 
                else
                {
                    printf("cant find vertex\n");
                    break;
                }*/
                
            }

            m->create_cellv(m,vs,3);
        }
        else
        {
            break;
        }
    }
    int_rb_tree_free(tree);
    fclose(infile);
    return node_reverse(n_c); 
}
void _WriteOff_(template_m* m,char const *filename)
{

    if((quote(m->v_begin(m)))->point_size!=3)
    {
        return ;
    }
#ifdef _WIN32
    FILE *outfile;
    fopen_s(&outfile,filename,"w");
#else
    FILE *outfile=fopen(filename,"w");
#endif 
    if(!outfile)
    {
        printf("cant open this file\n");
        return ;
    }
    fprintf(outfile,"OFF\n");
    fprintf(outfile,"%d %d %d\n",m->num_v(m),m->num_c(m),0);
    int *temp_v_id=(int*)malloc(sizeof(int)*m->num_v(m));
    int temp_id=0;
    for(auto v_it=m->v_begin(m);v_it!=m->v_end(m);v_it++)
    {
        temp_v_id[temp_id]=temp_id;
        ((template_v*)(quote(v_it)))->prop=(void*)(&temp_v_id[temp_id]);
        for(int j=0;j<3;j++)
        {
            fprintf(outfile,"%.7lf ",((template_v*)(quote(v_it)))->point[j]);
        }
        fprintf(outfile,"\n");
        temp_id++; 
    }
    int i=0;
    for(auto c_it=m->c_begin(m);c_it!=m->c_end(m);c_it++)
    { 
        fprintf(outfile,"%d ",((template_c*)(quote(c_it)))->vertices_size);
        for(auto cv_it=m->cv_begin(m,*((template_c*)(quote(c_it))));cv_it!=m->cv_end(m,*((template_c*)(quote(c_it))));cv_it++)
        {
            fprintf(outfile,"%d ",*((int*)((*cv_it).prop))); 
        }
        fprintf(outfile,"\n");
        i++;
    }
    free(temp_v_id);
    m->reset_v_prop(m); 

 //   printf("herere libo ***********************************\n"); 
  
   
   fclose(outfile);
}

//writecell 
void _WriteCell_(template_m*m,char const* filename)
{
#ifdef _WIN32
    FILE *outfile;
    fopen_s(&outfile,filename,"w");
#else
    FILE *outfile=fopen(filename,"w");
#endif
   if(!outfile)
   {
        printf("cant open this file\n");
        return ;
   }
   fprintf(outfile,"CELL\n");


   int back_ground=(quote(m->v_begin(m)))->point_size;
   //int back_ground=m->vertices.begin()->second->point_size;
   fprintf(outfile,"background_dim= %d\n",back_ground);
//#ifdef MANIFOLD_REQUIRE
   //if()
   fprintf(outfile,"manifold_dim= %d\n",m->dimension);
//#else
   //fprintf(outfile,"manifold_dim= 0\n");
//#endif
   fprintf(outfile,"simplex= %d\n",m->simplex);
   int num[3];
   num[0]=m->num_v(m);
   num[1]=m->num_hf(m);
   num[2]=m->num_c(m);
 //   printf("herere libo ***********************************\n"); 
   if(m->simplex==1)
   {

        fprintf(outfile,"%d %d %d\n",num[0],0,num[2]);
        //printf("numc_%d\n",m->num_c(m));
        int *temp_v_id=(int*)malloc(sizeof(int)*num[0]);
        int temp_id=0;
        for(auto v_it=m->v_begin(m);v_it!=m->v_end(m);v_it++)
        {
            temp_v_id[temp_id]=temp_id;
            ((template_v*)(quote(v_it)))->prop=(void*)(&temp_v_id[temp_id]);
            for(int j=0;j<back_ground;j++)
            {
                fprintf(outfile,"%.11lf ",((template_v*)(quote(v_it)))->point[j]);
            }
            fprintf(outfile,"\n");
            temp_id++; 
        }
        int i=0;
        for(auto c_it=m->c_begin(m);c_it!=m->c_end(m);c_it++)
        { 
            fprintf(outfile,"%d ",((template_c*)(quote(c_it)))->vertices_size);
            for(auto cv_it=m->cv_begin(m,*((template_c*)(quote(c_it))));cv_it!=m->cv_end(m,*((template_c*)(quote(c_it))));cv_it++)
            {
                fprintf(outfile,"%d ",*((int*)((*cv_it).prop))); 
            }
            fprintf(outfile,"\n");
            i++;
        }
        free(temp_v_id);
        m->reset_v_prop(m);

   }
   else
   {
       int temp_sum=0;
       for(auto c_it=m->c_begin(m);c_it!=m->c_end(m);c_it++)
       {
           temp_sum+=node_size(((template_c*)(quote(c_it)))->halffaces);
            
       }
       num[1]=temp_sum;
        fprintf(outfile,"%d %d %d\n",num[0],num[1],num[2]);
        int *temp_v_id=(int*)malloc(sizeof(int)*num[0]);
        int temp_id=0;
        for(auto v_it=m->v_begin(m);v_it!=m->v_end(m);v_it++)
        {
            temp_v_id[temp_id]=temp_id;
            ((template_v*)(quote(v_it)))->prop=(void*)(&temp_v_id[temp_id]);
            for(int j=0;j<back_ground;j++)
            {
                fprintf(outfile,"%lf ",((template_v*)(quote(v_it)))->point[j]);
            }
            fprintf(outfile,"\n");
            temp_id++; 
        }

        int *temp_hf_id=(int*)malloc(sizeof(int)*num[1]);
        temp_id=0;
        for(auto c_it=m->c_begin(m);c_it!=m->c_end(m);c_it++)
        {
            for(auto chf_it=m->chf_begin(m,*((template_c*)(quote(c_it))));chf_it!=m->chf_end(m,*((template_c*)(quote(c_it))));chf_it++)
            {
                temp_hf_id[temp_id]=temp_id;
                quote(chf_it)->prop=(void*)(&temp_hf_id[temp_id]);
                fprintf(outfile,"%d ",(*chf_it).vertices_size);
                for(auto hfv_it=m->hfv_begin(m,*chf_it);hfv_it!=m->hfv_end(m,*chf_it);hfv_it++)
                {
                    fprintf(outfile,"%d ",*((int*)(quote(hfv_it)->prop))); 
                }

                fprintf(outfile,"\n");
                temp_id++;
            }
        }


        for(auto c_it=m->c_begin(m);c_it!=m->c_end(m);c_it++)
        {
            int temp_size=node_size(((template_c*)(quote(c_it)))->halffaces);
            fprintf(outfile,"%d ",temp_size);
            for(auto chf_it=m->chf_begin(m,*((template_c*)(quote(c_it))));chf_it!=m->chf_end(m,*((template_c*)(quote(c_it))));chf_it++)
            {
                fprintf(outfile,"%d ",*((int*)(quote(chf_it)->prop)));
            }
            fprintf(outfile,"\n");
        }

        free(temp_v_id);
        free(temp_hf_id);
        m->reset_v_prop(m);
        m->reset_hf_prop(m);

   }
   
   fclose(outfile);
}

static inline int get_next_word_index_of_string (char* str,int temp_i)
{
   while(str[temp_i]!=' '&&str[temp_i]!='\0'&&str[temp_i]!='\n')
   {
        temp_i++;
   }
   while(str[temp_i]==' '&&str[temp_i]!='\0')
   {
        temp_i++;
   }
   return temp_i;
}
//
//只有off文件描述单形时才有效（我认为off文件还能描述n维流形）
//
void _ReadOff_(template_m *m,char const * filename, int n)
{
    int result=0;
#ifdef _WIN32
	FILE* infile;
	fopen_s(&infile,filename,"r");
#else
	FILE* infile=fopen(filename,"r");
#endif
    if(!infile)
	{
	    printf("cant't open this file\r\n");
	    return;
	}

    fseek(infile,0,SEEK_SET);
	char off[6];
	result=fscanf(infile,"%s",off);
    int mark=0;
    //printf("off\n");
    char str[300]={0},str1[100];
    if(strcmp("OFF",off)==0||strcmp("NOFF",off)==0)
    { 
	    int num[3];
        if(result=fscanf(infile,"%d %d %d",&num[0],&num[1],&num[2])==3)
        {
	        int rows=0,cols=0;
            fgets(str,300,infile);
	        while(rows<num[0]&&!feof(infile))
	        {
                fgets(str,300,infile);
                
	            template_v* v=m->create_vertex(m);
	            v->point_size=n;
                v->point=(double*)malloc(sizeof(double)*n);
                int temp_i=0;
                for(int i=0;i<n;i++)
	            {   
                    //result=fscanf(infile,"%lf ",&(v->point[i]));
                    // printf("begin\n");
                    result=sscanf(&str[temp_i],"%s ",str1);
                    // printf("%s\n",str1);
                    result=sscanf(str1,"%lf",&(v->point[i]));
                    temp_i=get_next_word_index_of_string(str,temp_i);
                    //printf("fdsdfsd\n");
                    //temp_i+=strlen(str1);
	            }
	            rows++;
                // if(rows<num[0])
                // {
                //     printf("eof\n");
                // }
                //printf("end %d\n",rows);
	        }
	   	    printf("num v %d\n",m->num_v(m));
		    rows=0;
	        int id;
	        while(!feof(infile)&&rows<num[1])
	        {
                 result=fscanf(infile,"%d",&cols);
               // result=fscanf(infile,"%d",&cols);
                template_v**temp_v=(template_v**)malloc(sizeof(template_v*)*cols);
                template_hf** temp_hf=(template_hf**)malloc(sizeof(template_hf*)*cols);
                for(int i=0;i<cols;i++)
	            {
                    result=fscanf(infile,"%d",&id);
                    template_v* v=NULL; 
                    v=m->get_vertexp(m,id);
                    if(v==NULL)
                    {
                        printf("can t find this vertex :%d\n",id);
                        return ;
                    }
		            temp_v[i]=v;
	            }

                for(int i=0;i<cols;i++)
                {
                    template_v* vs[2]={temp_v[i],temp_v[((i+1)%cols)]};
                    template_f* f=m->create_facev(m,vs,2);
                    temp_hf[i]=m->create_halfface(m,f,vs,2);
                }
	            m->create_cellf(m,temp_hf,cols);
                free(temp_hf);
                free(temp_v);
                rows++; 
                if(cols>mark)
                {
                    mark=cols;
                }
	        }
	   //printf("%d\r\n",m->num_f(m));
	    }
        else
        { 
	        printf("this file is not complete\r\n"); 
	        return;
	   }
    }
    else
	{
	    printf("this is not off\r\n");
	    return;
	}
    if(mark==3)
    {
        m->simplex=1;
        m->dimension=2;
    }
    else if(mark==0)
    {
        m->dimension=0;
        m->simplex=1;
    }
    else
    {
        m->dimension=2;
        m->simplex=0;
    }
    fclose(infile);
}




typedef struct TEMP_OBJ_CELL_INFO{
    int**vids;
    int len;
    OBJ_CELL_PROP* ocp; 
}TEMP_OBJ_CELL_INFO;


void temp_obj_cell_info_init(TEMP_OBJ_CELL_INFO* toci)
{
    toci->vids=NULL;
    toci->ocp=NULL;
    toci->len=0;
}
char** split(char *  targetString, const char  delimiter,int *  length)
{
    Node* re1=NULL;re1=node_overlying(re1,NULL);
    int len=strlen(targetString);
    for(int i=0;i<len;i++)
    {
        if(targetString[i]==delimiter||targetString[i]=='\n')
        {
            if(re1->value!=NULL)
            {
                re1=node_overlying(re1,NULL);
            }
        } 
        else
        {
            Node* sub_node=(Node*)(re1->value);
            sub_node=node_overlying(sub_node,&(targetString[i])); 
            re1->value=sub_node;
        } 
    } 
    if(re1->value==NULL)
    {
        re1=node_remove(re1,re1);
    } 

    *length=node_size(re1);
    if(re1==NULL)
    {
        return NULL;
    }
    char**re=(char**)malloc(sizeof(char*)*(*length));
    int i=0;
    for(Node* nit=node_reverse(re1);nit!=NULL;nit=(Node*)(nit->Prev))
    {
        Node* sub_node=(Node*)(nit->value);
        int j=0;
        re[i]=(char*)malloc(sizeof(char)*(node_size(sub_node)+1));
        memset(re[i],0,node_size(sub_node)+1);
        for(Node* nit1=node_reverse(sub_node);nit1!=NULL;nit1=(Node*)(nit1->Prev))
        {
            re[i][j]=*((char*)(nit1->value));
            j++;
        }
        free_node(sub_node);
        i++;
    } 
    free_node(re1);
    return re;
}

static void my_sscanf(char * str,int* i1,int* i2,int *i3)
{
    int len=0;*i1=-1;*i2=-1;*i3=-1;
    char** words=split(str,'/',&len);
    int len1=strlen(str),num=0;
    for(int i=0;i<len1;i++)
    {
        if(str[i]=='/')
        {
            num++;
        }
    } 
    int * indexs[3]={i1,i2,i3};
    if(num==2&&len==2)
    {
        indexs[1]=i3; 
    }  
    for(int i=0;i<len;i++)
    {
        sscanf(words[i],"%d",indexs[i]);
        free(words[i]);
    }
    SAFE_FREE(words);
}
static double** get_double_array_from_node(Node* n)
{
    int len=node_size(n);
    double** re=(double**)malloc(sizeof(double*)*len);
    int i=0;
    for(Node*nit=node_reverse(n);nit!=NULL;nit=(Node*)(nit->Prev))
    {
        re[i]=(double*)(nit->value);
        i++;
    }
    return re;
}

void _ReadObj_(Mesh* m,char const * filename)
{
#ifdef _WIN32
    FILE *infile;
    fopen_s(&infile,filename,"r");
#else
    FILE *infile=fopen(filename,"r");
#endif
    if(!infile)
    {
        printf("can't open this file %s\n",filename);
    }
    fseek(infile,0,SEEK_SET);
    int mark=0;
    char str[400]={0},str1[300]={0};

    Node* tree1=NULL,*tree2=NULL,*tree3=NULL;

    int id=-1,id1=-1,id2=-1;
    template_v* v=NULL;

    char mtlname[100]={0},group_info[300]={0},group_info1[300]={0};
    OBJ_MESH_PROP*omp=(OBJ_MESH_PROP*)malloc(sizeof(OBJ_MESH_PROP));
    obj_mesh_prop_init(omp);    
    Node* polygons=NULL;polygons=node_overlying(polygons,NULL);

    while(!feof(infile))
    {
        fgets(str,400,infile);
        //printf("%s",str);
        if(feof(infile))
        {
            break;
        }
        if(str[0]=='#')
        {
            continue;
        }
        else if(str[0]=='v'&&str[1]=='t'&&str[2]==' ')
        {
            double *point=(double*)malloc(sizeof(double)*2);
            tree1=node_overlying(tree1,point);
            sscanf(&str[3],"%lf %lf ",&(point[0]),&(point[1])); 
        }
        else if(str[0]=='v'&&str[1]=='n'&&str[2]==' ')
        {
            double *point=(double*)malloc(sizeof(double)*3);
            tree2=node_overlying(tree2,point);
            sscanf(&str[3],"%lf %lf %lf",&(point[0]),&(point[1]),&(point[2]));
 
        }
        else if(str[0]=='v'&&str[1]==' ')
        {
            double *point=(double*)malloc(sizeof(double)*3);
            sscanf(&str[2],"%lf %lf %lf",&(point[0]),&(point[1]),&(point[2]));
            tree3=node_overlying(tree3,point); 
        }
        else if(str[0]=='f'&&str[1]==' ')
        { 
            if(strcmp(group_info,group_info1)!=0)
            {
                polygons=node_overlying(polygons,NULL); 
                strcpy(group_info1,group_info); 
            }
            Node* sub_polygons=(Node*)(polygons->value);

            int fv_rows=0;
            memset(str1,0,sizeof(char)*300);
            char**words=split(&str[2],' ',&fv_rows); 
            fv_rows>mark?mark=fv_rows:mark=mark;
            
            TEMP_OBJ_CELL_INFO* toci=(TEMP_OBJ_CELL_INFO*)malloc(sizeof(TEMP_OBJ_CELL_INFO));
            toci->len=fv_rows;
            
            toci->vids=(int**)malloc(sizeof(int*)*toci->len);
            toci->ocp=(OBJ_CELL_PROP*)malloc(sizeof(OBJ_CELL_PROP));
            obj_cell_prop_init(toci->ocp);toci->ocp->n=toci->len;
            if(strlen(mtlname)>0)
            {
                toci->ocp->mtlname=(char*)malloc(sizeof(char)*(strlen(mtlname)+1)); 
                strcpy( toci->ocp->mtlname,mtlname);
            }
            if(strlen(group_info)>0)
            {
                toci->ocp->group_info=(char*)malloc(sizeof(char)*(strlen(group_info)+1));
                strcpy(toci->ocp->group_info,group_info);
            } 
            for(int i=0;i<toci->len;i++)
            {
                id=-1;id1=-1;id2=-1;
                my_sscanf(words[i],&id,&id1,&id2);
                if(id<0)
                {
                    printf("cuow************************\n");
                    // if(words[i][strlen(words[i])-1]=='\n')
                    // {
                    //     printf("zhengshi %d\n",strlen(words[i]));
                    // } 
                    //printf("cuwu %d %d %s\n",i,strlen(str),words[i]);
                    printf("%s\n",str);
                    return;
                }
                id--;id1--;id2--;
                // printf("%d %d %d\n",id,id1,id2);
                toci->vids[i]=(int*)malloc(sizeof(int)*3);
                toci->vids[i][0]=id;toci->vids[i][1]=id1;toci->vids[i][2]=id2;
                free(words[i]);
            }
            SAFE_FREE(words);
            sub_polygons=node_overlying(sub_polygons,toci);
            polygons->value=sub_polygons;
        }
        else if (str[0]=='u'&&str[1]=='s'&&str[2]=='e'&&str[3]=='m'&&str[4]=='t'&&str[5]=='l'&&str[6]==' ')
        {
            sscanf(&str[7],"%s",mtlname);
        }
        else if (str[0]=='m'&&str[1]=='t'&&str[2]=='l'&&str[3]=='l'&&str[4]=='i'&&str[5]=='b'&&str[6]==' ')
        {
            omp->mtlibname=(char*)malloc(sizeof(char)*(strlen(str)-6));
            memset(omp->mtlibname,0,sizeof(char)*(strlen(str)-6));
            sscanf(&str[7],"%s",omp->mtlibname);
        }
        else if (str[0]=='g'&&str[1]==' ')
        {
            sscanf(&str[2],"%s",group_info);
        }
    }
    double** tree1_a=get_double_array_from_node(tree1);
    double** tree2_a=get_double_array_from_node(tree2);
    double** tree3_a=get_double_array_from_node(tree3);

    printf("size polygons:%d\n",node_size(polygons));
    for(Node* nit=node_reverse(polygons);nit!=NULL;nit=(Node*)(nit->Prev))
    {
        Node* sub_polygons=(Node*)(nit->value);
        Int_RB_Tree* temp_tree=(Int_RB_Tree*)malloc(sizeof(Int_RB_Tree));
        int_rb_tree_init(temp_tree); 
        for(Node* nit1=node_reverse(sub_polygons);nit1!=NULL;nit1=(Node*)(nit1->Prev))
        {
            TEMP_OBJ_CELL_INFO*toci=(TEMP_OBJ_CELL_INFO*)(nit1->value);
            template_v** temp_v=(template_v**)malloc(sizeof(template_v*)*toci->len);
            
            toci->ocp->vt=(double**)malloc(sizeof(double*)*toci->len);memset(toci->ocp->vt,0,sizeof(double*)*toci->len);
            toci->ocp->vn=(double**)malloc(sizeof(double*)*toci->len);memset(toci->ocp->vn,0,sizeof(double*)*toci->len);
            
            for(int i=0;i<toci->len;i++)
            {
                template_v* v=(template_v*)(temp_tree->find(temp_tree,toci->vids[i][0]));
                if(v==NULL)
                {
                    double* p1=tree3_a[toci->vids[i][0]];
                    if(p1==NULL)
                    {
                        printf("cuowuuu1 %d\n",toci->vids[i][0]);
                        return ; 
                    }
                    v=m->create_vertexv(m,p1,3); 
                    if(v!=NULL)
                    {
                        temp_tree->insert(temp_tree,toci->vids[i][0],v);
                    }
                    else
                    {
                        printf("cuowu v is NULL\n");
                        return ;
                    }
                } 
                temp_v[i]=v;
                if(toci->vids[i][1]>=0)
                {
                    double* p=tree1_a[toci->vids[i][1]];
                    toci->ocp->vt[i]=(double*)malloc(sizeof(double)*2);
                    toci->ocp->vt[i][0]=p[0];toci->ocp->vt[i][1]=p[1];
                } 
                if(toci->vids[i][2]>=0)
                {
                    double*p=tree2_a[toci->vids[i][2]]; 
                    toci->ocp->vn[i]=(double*)malloc(sizeof(double)*3);
                    toci->ocp->vn[i][0]=p[0];toci->ocp->vn[i][1]=p[1];toci->ocp->vn[i][2]=p[2];
                } 
                free(toci->vids[i]);
            } 
            template_hf**temp_hf=(template_hf**)malloc(sizeof(template_hf*)*toci->len);
            int flag=0;
            for(int i=0;i<toci->len;i++)
            {
                template_v*vs[2]={temp_v[i],temp_v[(i+1)%toci->len]};
                template_f*f=m->create_facev(m,vs,2); 
                temp_hf[i]=m->create_halfface(m,f,vs,2);
                if(temp_hf[i]==NULL)
                {
                    flag=1;
                    
                    break;
                }
            }
            if(flag==1)
            {
                for(int i=0;i<toci->len;i++)
                {
                    template_v* v=m->create_vertexv(m,temp_v[i]->point,3);
                    temp_v[i]=v;
                }
                for(int i=0;i<toci->len;i++)
                {
                    template_v*vs[2]={temp_v[i],temp_v[(i+1)%toci->len]};
                    template_f*f=m->create_facev(m,vs,2); 
                    temp_hf[i]=m->create_halfface(m,f,vs,2);
                }
            }
            template_c*c=m->create_cellf(m,temp_hf,toci->len);
            c->prop=toci->ocp;
            free(temp_v);free(temp_hf); 
            free(toci->vids);
            free(toci);
        }
        int_rb_tree_free(temp_tree);
        free_node(sub_polygons);
    }

    free_node(polygons);
    free(tree1_a);free(tree2_a);free(tree3_a);

    free_node_value(tree1);free_node_value(tree2);free_node_value(tree3);
    free_node(tree1);free_node(tree2);free_node(tree3);
    if(omp->mtlibname!=NULL&&strlen(omp->mtlibname)>0)
    {
        (m->prop=omp);
    }
    else
    {
        obj_mesh_prop_free(omp);
    }
 
    fclose(infile);
    if(mark==3)
    {
        m->simplex=1;
        m->dimension=2;
    }
    else if(mark==0)
    {
        m->dimension=0;
        m->simplex=1;
    }
    else
    {
        m->dimension=2;
        m->simplex=0;
    }
}
//         
//void export_obj_from_node
//       

static inline  int mystrcmp(char* str1,char* str2)
{ 
    return str1==NULL?((str2==NULL||strlen(str2)==0)?0:(-1)):((str2==NULL)?(strlen(str1)==0?0:-1):(strcmp(str1,str2)));
}
//还要支持"g"字段
void export_obj_from_node(Node* node,char* filename,char * mtlibname)
{
    if(node==NULL)
    {
        return;
    }
#ifdef _WIN32
    FILE *outfile;
    fopen_s(&outfile,filename,"w");
#else
    FILE *outfile=fopen(filename,"w");
#endif
    if(!outfile)
    {
        printf("can't open this file\n"); 
        return ;
    }
    if(mtlibname!=NULL&&strlen(mtlibname)!=0)
    {
        fprintf(outfile,"mtllib %s\n",mtlibname);
    }

    Int_RB_Tree* tree=(Int_RB_Tree*)malloc(sizeof(Int_RB_Tree));
    int_rb_tree_init(tree);
    Node* mtl_class=NULL;  

    int id=1;
    Node* vertices=NULL,*node_vt=NULL;
    for(Node* nit=node;nit!=NULL;nit=(Node*)(nit->Next))
    {
        template_c* c=(template_c*)(nit->value);
        if(mtlibname!=NULL&&strlen(mtlibname)!=0)
        {
            OBJ_CELL_PROP* ocp=(OBJ_CELL_PROP*)(c->prop); 
            Node* nit1=mtl_class;char * mtlname=(ocp==NULL?NULL:ocp->mtlname);
            for(;nit1!=NULL;nit1=(Node*)(nit1->Next))
            {
                if(mystrcmp(mtlname,(char*)(nit1->traits))==0)
                {break;} 
            }
            if(nit1!=NULL)
            {
                Node* node_mtl=(Node*)(nit1->value);
                node_mtl=node_overlying(node_mtl,c);
                nit1->value=node_mtl;
            } 
            else
            {
                Node* node_mtl=node_overlying(NULL,c);
                mtl_class=node_overlying(mtl_class,node_mtl);
                mtl_class->traits=mtlname;
            }
        } 
        for(int i=0;i<c->vertices_size;i++)
        {
            template_v*v=c->vertices[i];
            if(tree->find(tree,v->id)==NULL)
            {
                int* value=(int*)malloc(sizeof(int));
                *value=id;
                tree->insert(tree,v->id,value);
                vertices=node_overlying(vertices,v);
                id++;
            } 
        } 
    }
    for(Node* nit=node_reverse(vertices);nit!=NULL;nit=(Node*)(nit->Prev))
    {
        template_v* v=(template_v*)(nit->value);
        fprintf(outfile,"v %lf %lf %lf\n",v->point[0],v->point[1],v->point[2]); 
    } 
    if(mtlibname==NULL||strlen(mtlibname)==0)
    {
        mtl_class=node_overlying(NULL,node_copy(node));
    } 
    

    id=1;
    for(Node* nit=mtl_class;nit!=NULL;nit=(Node*)(nit->Next))
    {
        Node* node_mtl=(Node*)(nit->value);
        (mtlibname==NULL||strlen(mtlibname)==0)?1:((nit->traits!=NULL&&strlen((char*)(nit->traits))!=0)?fprintf(outfile,"usemtl %s\n",(char*)(nit->traits)):1);
        for(Node* nit1=node_mtl;nit1!=NULL;nit1=(Node*)(nit1->Next))
        {
            template_c* c=(template_c*)(nit1->value);
            OBJ_CELL_PROP* ocp=(OBJ_CELL_PROP*)(c->prop);
            if(ocp!=NULL&&ocp->vt!=NULL&&ocp->vt[0]!=NULL)
            { 
                for(int i=0;i<c->vertices_size;i++)
                {
                    fprintf(outfile,"vt %lf %lf \n",ocp->vt[i][0],ocp->vt[i][1]);
                    id++;
                }  
            }       
            fprintf(outfile,"f ");
            for(int i=0;i<c->vertices_size;i++)
            {
                template_v* v=c->vertices[i];
                int* value=(int*)(tree->find(tree,v->id));
                if(mtlibname==NULL||strlen(mtlibname)==0)
                {
                    fprintf(outfile,"%d ",*value); 
                }
                else
                {
                   if(ocp!=NULL&&ocp->vt!=NULL&&ocp->vt[0]!=NULL)
                   {
                        fprintf(outfile,"%d/%d ",*value,id-c->vertices_size+i);
                   }
                   else
                   {
                        fprintf(outfile,"%d ",*value); 
                   } 
                }
            } 
            fprintf(outfile,"\n"); 
        }
        free_node(node_mtl);
    }  
    free_node(vertices);
    free_node(mtl_class);
    int_rb_tree_free_value(tree);
    int_rb_tree_free(tree);
    fclose(outfile);
}


void static inline binary_read_one_line(FILE* infile,char* str)
{
    memset(str,0,sizeof(char)*300);
    char temp='\0';

    fread(&temp,sizeof(char),1,infile);
    int i=0;
    while(temp!='\n')
    {
        str[i]=temp;
        i++;
        fread(&temp,sizeof(char),1,infile);
    } 
}

void _ReadPly_(template_m*m,char const *filename)
{
    int result;
#ifdef _WIN32
    FILE *infile;
    fopen_s(&infile,filename,"rb");
#else
    FILE *infile=fopen(filename,"rb");
#endif
    if(!infile)
    {
        printf("can't open this file %s\n",filename);
    }
    fseek(infile,0,SEEK_SET); 

    char str[300]={0},str1[300]={0},temp_str[300]={0};
    binary_read_one_line(infile,str);
   
    printf("is %s\n",str);
    int num_v=0,num_f=0;
    if(strcmp("ply",str)!=0)
    {
        return ;
    }
    // printf("is ply:%s\n",off);
    // fscanf(infile,"%s",str);
    binary_read_one_line(infile,str);
    //int mark_vertex=0;
    int is_binary=0;
    //Node* node_type_size=NULL;
    char type_str[6][12]={0}; 
    
    while(strcmp(str,"end_header")!=0)
    {
        sscanf(str,"%s",str1); 
        if(strcmp(str1,"element")==0)
        {
            int num=0;
            sscanf(str+strlen(str1),"%s %d",temp_str,&num);
            if(strcmp(temp_str,"vertex")==0)
            {
                num_v=num;
                int i=0;
                binary_read_one_line(infile,str);
                sscanf(str,"%s",str1); 
                while(strcmp(str1,"property")==0 )
                {
                    sscanf(str+strlen(str1),"%s",temp_str);

                    strcpy(type_str[i],temp_str);
                    i++;
                    binary_read_one_line(infile,str);
                    sscanf(str,"%s",str1);
                }
                continue;
            } 
            else if(strcmp(str,"face")==0)
            {
                num_f=num;
            }
        }
        else if(strcmp(str1,"format")==0)
        {
            sscanf(str+strlen(str1),"%s",temp_str);
            if(strcmp(temp_str,"ascii")==0)
            {
                is_binary=0;
            }
            else
            {
                is_binary=1;
            }
        }
        binary_read_one_line(infile,str);
    } 
    printf("str:%s\n",str);
    if(num_f>0)
    {
        m->dimension=2;
    }
    int size=0; 
    for(int i=0;i<6;i++)
    {
        if(strlen(type_str[i])==0)
        {
            break;
        }

        size++;
        printf("%s %d\n",type_str[i],size);
    }
    if(is_binary)
    {
        printf("is binary num_v:%d num_f:%d\n",num_v,num_f);
        if(strcmp(type_str[0],"float")==0)
        {
            for(int i=0;i<num_v;i++)
            {
                double p[3]={0};
                float x;
                fread(&x,sizeof(float),1,infile);
                p[0]=x;
                fread(&x,sizeof(float),1,infile);
                p[1]=x;
                fread(&x,sizeof(float),1,infile);
                p[2]=x; 
                template_v* v=m->create_vertexv(m,p,3);
                for(int j=0;j<size-3;j++)
                {
                    fread(&x,sizeof(float),1,infile);
                }
                printf("%d\n",i);
            }
        }
    }
    else
    {
        printf("ascii num_v:%d num_f:%d size:%d\n",num_v,num_f,size);
        if(strcmp(type_str[0],"float")==0)
        {
            for(int i=0;i<num_v;i++)
            {
                double p[3]={0};
                binary_read_one_line(infile,str);
                sscanf(str,"%lf %lf %lf",&p[0],&p[1],&p[2]);
                template_v* v=m->create_vertexv(m,p,3);
                //printf("%lf %lf %lf\n",p[0],p[1],p[2]);

            } 
        }
    }

    fclose(infile);
}